package com.xiongjie.util;

import io.reactiverse.pgclient.*;
import io.vertx.config.ConfigRetriever;
import io.vertx.config.ConfigRetrieverOptions;
import io.vertx.config.ConfigStoreOptions;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonObject;
import java.util.List;
import java.util.stream.Collector;

import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toList;

/**
 * 封装reactive-pg-client.
 */
final public class PgWrapper {

  private final PgClient pgClient;
  private final JsonObject sqlConfig;

  private PgWrapper(PgPool pgPool, JsonObject sqlConfig) {
    this.pgClient = pgPool;
    this.sqlConfig = sqlConfig;
  }

  /**
   * 1.使用vert.x+配置文件，创建pgclient，同时执行数据库操作
   * @param vertx
   * @param pgConfig
   * @param sqlResourcePath
   * @return
   */
  public static Future<PgWrapper> createInstance(Vertx vertx, JsonObject pgConfig, String sqlResourcePath) {
    final ConfigStoreOptions fileStore = new ConfigStoreOptions()
      .setType("file")
      .setFormat("yaml")
      .setOptional(false)
      .setConfig(new JsonObject()
        .put("path", sqlResourcePath));

    final ConfigRetrieverOptions options = new ConfigRetrieverOptions()
      .setScanPeriod(0)
      .setIncludeDefaultStores(false)
      .addStore(fileStore);

    final Future<PgWrapper> future = Future.future();
    ConfigRetriever.create(vertx, options).getConfig(ar -> {
      if (ar.succeeded()) {
        final JsonObject config = ar.result();

        //去掉sql的行尾
        for (String name : config.fieldNames()) {
          final JsonObject item = config.getJsonObject(name);
          item.put("sql", item.getString("sql").trim());
          item.put("failure", name);
        }

        PgPool pgPool=PgClient.pool(vertx, new PgPoolOptions(PgPoolOptions.fromEnv().toJson().mergeIn(pgConfig)));
        future.complete(new PgWrapper(pgPool, config));
      } else {
        System.out.println("创建pg失败！");
      }
    });
    return future;
  }

  /**
   * 2.具体的查询代码封装方法
   * @param key
   * @param arguments
   * @param collector
   * @param resultHandler
   * @param <R>
   */
  public <R> void queryOne(String key, Tuple arguments, Collector<Row, ?, List<R>> collector, Handler<AsyncResult<R>> resultHandler) {
    final String sql = sqlConfig.getJsonObject(key).getString("sql");

    pgClient.preparedQuery(sql, arguments, collector, ar -> {
      if (ar.succeeded()) {
        PgResult<List<R>> result = ar.result();
        if (result.size() == 1) {
          resultHandler.handle(Future.succeededFuture(result.value().get(0)));
        } else {
          System.out.println("查询失败！");
        }
      } else {
        System.out.println("查询失败！");
      }
    });
  }

  /**
   * 3.将查询结果封装成json
   * @return
   */
  public static Collector<Row, ?, List<JsonObject>> collectJsonObject() {
    return mapping(row -> (JsonObject) row.getJson(0).value(), toList());
  }
}
